package com.koron.order.overhaul.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.koron.bean.base.Response;
import com.koron.bean.query.OrderItem;
import com.koron.bean.query.PageQuery;
import com.koron.bean.system.staff.StaffBean;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.common.core.util.CodeTools;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Stream;

/**
 * @author twcao
 * @title: CommonUtils
 * @projectName GDH_EAM_V2
 * @description: 共用工具类
 * @date 2021/9/116:37
 */
@Slf4j
public class CommonUtils {

    /**
     * 设置创建人和修改人
     * @param vo 业务数据实体
     * @param staffBean 用户信息
     */
    public static void update(UpdateParameter vo, StaffBean staffBean) {
        Assert.notNull(staffBean, "用户信息为空");
        Assert.notNull(vo, "基础参数为空");
        if(StringUtils.isBlank(vo.getId())) {
            // 新增
            vo.setCreateBy(staffBean.getAccount());
            vo.setCreateByName(staffBean.getName());
            vo.setCreateTime(new Date());
        }
        // 修改
        vo.setUpdateBy(staffBean.getAccount());
        vo.setUpdateByName(staffBean.getName());
        vo.setUpdateTime(new Date());
    }

    public static void update(UpdateParameter vo, String account, String name) {
        Assert.notNull(account, "账号不能为空");
        Assert.notNull(name, "名字不能为空");
        if(StringUtils.isBlank(vo.getId())) {
            // 新增
            vo.setCreateBy(account);
            vo.setCreateByName(name);
            vo.setCreateTime(new Date());
        }
        // 修改
        vo.setUpdateBy(account);
        vo.setUpdateByName(name);
        vo.setUpdateTime(new Date());
    }

    public static void update(List<? extends UpdateParameter> vos, String account, String name) {
        if(CollectionUtils.isEmpty(vos)) {
            return;
        }
        Assert.notNull(account, "账号不能为空");
        Assert.notNull(name, "名字不能为空");
        vos.stream().forEach(vo -> update(vo, account, name));
    }

    /**
     * 设置删除默认标志（未删除）,如果已存在，不做任何处理
     * @param flag 删除标志位
     */
    public static void update(DeleteFlag flag) {
        Assert.notNull(flag, "实体信息为空");
        if(Objects.isNull(flag.getDeleteFlag())) {
            flag.setDeleteFlag(false);
        }
    }

    /**
     * 设置删除默认标志（未删除）,如果已存在，不做任何处理
     * @param flags 删除标志位
     */
    public static void update(List<? extends DeleteFlag> flags) {
        Assert.noNullElements(flags, "实体不能为空");
        flags.stream().forEach(flag -> update(flag));
    }

    /**
     * 设置排序值,从1开始
     * @param sortable
     */
    public static void sorted(List<? extends Sortable> sortable) {
        if(CollectionUtils.isEmpty(sortable)) {
            return;
        }
        Stream.iterate(0, i -> i + 1).limit(sortable.size()).forEach(i -> sortable.get(i).setSort(i + 1));
    }

    public static <T> T getObject(boolean expression, String msg, Response<T> resp) {
        Assert.isTrue(expression, msg);
        return resp.getData();
    }

    public static <T> T ok(Response<T> resp) {
        return getObject(resp != null && resp.getCode() == 200, resp == null ? "远程调用失败" : resp.getDescription(), resp);
    }

    /**
     * 获取编码
     * @param prefix 前缀
     * @param length 流水号长度
     * @return 最新的编码
     */
    public static String getCodeNo(String prefix, Integer length) {
        EamUser currentUser = ThreadLocalContext.get();
        String orgName = currentUser.getPrefix();
        Assert.hasText(orgName, "组织编码前缀不能为空");
        // 转成大写
        orgName = StringUtils.upperCase(orgName);
        return CodeTools.getCodeNo(prefix + orgName, length);
    }

    /**
     * 将树状嵌套，平铺成列表，如果没有id，会生成节点id，根节点parentId设置为0
     * @param list 嵌套的列表
     * @return 平铺后的列表
     */
    public static List<? extends Children> tileToList(List<? extends Children> list) {
        List<Children> target = new ArrayList<>();
        if(CollectionUtils.isEmpty(list)) {
            return target;
        }
        Iterator<? extends Children> iterator = list.iterator();
        while (iterator.hasNext()) {
            // 当前节点
            Children node = iterator.next();
            node.setId(StringUtils.isBlank(node.getId()) ? uuid() : node.getId());
            target.add(node);
            List<Children> children = node.getChildren();
            if(CollectionUtils.isEmpty(children)) {
                continue;
            }
            children.stream().forEach(child -> {
                child.setParentId(node.getId());
            });
            target.addAll(tileToList(children));
            node.setChildren(null);
            node.setParentId(StringUtils.isBlank(node.getParentId()) ? "0" : node.getParentId());
        }
        return target;
    }

    /**
     * 将列表转成树状结构
     * @param tree
     * @return
     */
    public static <X> List<X> listToTree(List<X> tree, Class<X> clazz) {
        String id = "id";
        String pid = "parentId";
        String child = "children";
        JSONArray arr = JSONArray.parseArray(JSON.toJSONString(tree));
        JSONArray r = new JSONArray();
        JSONObject hash = new JSONObject();
        for(int i=0;i<arr.size();i++){
            JSONObject json = (JSONObject) arr.get(i);
            hash.put(json.getString(id), json);
        }
        for(int j=0;j<arr.size();j++){
            JSONObject aVal = (JSONObject) arr.get(j);
            JSONObject hashVP = (JSONObject) hash.get(aVal.get(pid).toString());
            if(hashVP!=null){
                if(hashVP.get(child)!=null){
                    JSONArray ch = (JSONArray) hashVP.get(child);
                    ch.add(aVal);
                    hashVP.put(child, ch);
                }else{
                    JSONArray ch = new JSONArray();
                    ch.add(aVal);
                    hashVP.put(child, ch);
                }
            }else{
                r.add(aVal);
            }
        }
        return JSONArray.parseArray(JSON.toJSONString(r), clazz);
    }

    public static String uuid() {
        return UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
    }

    public static void addTableAlias(PageQuery query, String tableAlias) {
        List<OrderItem> orders = query.getOrders();
        if(CollectionUtils.isEmpty(orders)) {
            return;
        }
        orders.stream().forEach(item -> item.setPrefix(tableAlias));
    }
}
